import React, { useState } from 'react'
import "./App.scss";
import "bootstrap/dist/css/bootstrap.min.css";
import FileSearch from "./components/FileSearch";
import FileList from "./components/FileList";
import ButtonBtn from "./components/ButtonBtn";
import TabList from "./components/TabList";
import Loader from "./components/Loader";
import { message } from 'antd';
import { faPlus, faFileImport, faSave } from "@fortawesome/free-solid-svg-icons";
import { Editor } from "@tinymce/tinymce-react";
import { v4 as uuidv4 } from 'uuid';
import { flattenArr, objToArr } from './utils/help'
import fileHelper from './utils/fileHelp'
import useIpcRenderer from './hooks/useIpcRenderer'
const Store = window.require('electron-store')
const fs = window.require('fs')
const { join, basename, extname, dirname } = window.require('path')
const { remote, ipcRenderer } = window.require('electron')
const fileStore = new Store({'name': 'FilesData'})
const settingsStore = new Store({name: 'Settings'})
const getAutoSync =  ['accessKey', 'secretKey', 'bucketName', 'enableAutoSync'].every(key => !!settingsStore.get(key))
const saveFilesToStore = (files) => {
  const filesStoreObj = objToArr(files).reduce((result, file) => {
    const { id, path, title, createAt, isSynced, updatedAt } = file
    result[id] = {
      id, 
      path,
      title,
      createAt,
      isSynced, 
      updatedAt
    }
    return result
  },{})
  fileStore.set('files', filesStoreObj)
}
function App() {
  const [ files, setFiles ] = useState(fileStore.get('files') || [])
  const [ activedFileId, setActivedFileId ] = useState('')
  const [ openedFileIDs, setOpenedFileIDs] = useState([])
  const [ unsavedFilesIds, setUnsavedFilesIds] = useState([])
  const [ searchedFiles , setSearchedFiles] = useState([])
  const [ loading , setLoading] = useState(false)
  const filesArr = objToArr(files)
  const saveLocation = settingsStore.get('savedFileLocation') || remote.app.getPath('documents')
  const fileClick = (fileId) => {
    setActivedFileId(fileId)
    const currentFile = files[fileId]
    const { id, title, path, isLoaded } = currentFile
    if(!isLoaded) {
       if(getAutoSync) {
        ipcRenderer.send('download-file', {key: `${title}.md`, path, id})
      }else{
        fileHelper.readFile(currentFile.path).then(value => {
          const newFile = { ...currentFile, body: value, isLoaded: true}
          setFiles({...files, [fileId]: newFile})
        })
      }
    }
    if(!openedFileIDs.includes(fileId)) {
      setOpenedFileIDs([...openedFileIDs, fileId])
    }
  }
  const tabClick = (fileId) => {
    setActivedFileId(fileId)
  } 
  const closeTab = (id) =>  {
    let tabsWithout = openedFileIDs.filter(fileId => fileId !== id)
    let list = unsavedFilesIds.filter(fileId => fileId !== id)
    setUnsavedFilesIds(list)
    setOpenedFileIDs(tabsWithout)
    if(tabsWithout.length > 0) {
      setActivedFileId(tabsWithout[0])
    }else{
      setActivedFileId('')
    }
  }
  const handleEditorChange = (id, value) => {
    if(files[id].body === value) return
    const newFile = { ...files[id], body: value}
    setFiles({...files, [id]: newFile})
    if(!unsavedFilesIds.includes(id)) {
      setUnsavedFilesIds([...unsavedFilesIds, id])
    }
  }
  const deleteFile = (id) => {
    const { [id]: value, ...afterDelete } = files
    if(files[id].isNew) {
      delete files[id]
      setFiles(afterDelete)
      closeTab(id)
      return
    }
    fileHelper.deleteFile(files[id].path).then(() => {
      closeTab(id)
      setFiles(afterDelete)
      saveFilesToStore(afterDelete)
    }).catch(err => {
      closeTab(id)
      setFiles(afterDelete)
      saveFilesToStore(afterDelete)
    })
  }
  const isExist = (path) => {
    !fs.existsSync(path) && fs.mkdirSync(path)
  }
  const updateFileName = (id, title, isNew) => {
    isExist(join(saveLocation, 'myfile'))
    const newPath = isNew ? join(saveLocation, 'myfile' ,`${title}.txt`) : join(dirname(files[id].path), `${title}.txt`)
    let sameName = Object.values(files).find(file => file.title === title)
    if(sameName) {
      setFiles({...files})
      message.info('已有同名文件')
      return
    }
    const modifiedFile = { ...files[id], title, isNew: false, path: newPath }
    if(isNew) {
      fileHelper.writeFile(newPath, files[id].body).then(() => {
        setFiles({...files, [id]: modifiedFile})
        saveFilesToStore({...files, [id]: modifiedFile})
      })
    }else{
      const oldPath = files[id].path
      fileHelper.renameFile(oldPath, newPath).then(() => {
        setFiles({...files, [id]: modifiedFile})
        saveFilesToStore({...files, [id]: modifiedFile})
      })
    }
  }
  const fileSearch = (keyword) => {
    const newFiles = filesArr.filter(file => file.title.includes(keyword))
    setSearchedFiles(newFiles)
  }
  const createNewFile = () => {
    const newID = uuidv4()
    const newFile = {
      id: newID,
      title: '',
      body: '请输入',
      createAt: new Date().getTime(),
      isNew: true
    }
    setFiles({[newID]: newFile, ...files})
  }
  const saveFile = () => {
    const { path, body, title } = activeFile
    fileHelper.writeFile(path, body).then((data) => {
      message.success('保存成功');
      setUnsavedFilesIds(unsavedFilesIds.filter(id => id !== activeFile.id))
      if(getAutoSync) {
        ipcRenderer.send('upload-file', {
          key: `${title}.txt`,
          path
        })
      }
    }).catch(err => {
      console.log(err)
    })
  }
  const importFiles = () => {
    remote.dialog.showOpenDialog({
      title: '选择导入的文件',
      properties: ['openFile', 'multiSelections'],
      filters: [{
        name: 'txt files', extensions: ['txt']
      }]
    }).then((result) => {
      if(!result.canceled) {
        let filePaths = result.filePaths
        if(filePaths.length > 0) {
          // filter out the path
          const filteredPaths = filePaths.filter(path => {
            const alreadyAdded = Object.values(files).find(file => {
              return file.path === path
            })
            return !alreadyAdded
          })
          const importFilesArr = filteredPaths.map(path => {
            return {
              id: uuidv4(),
              title: basename(path, extname(path)),
              path
            }
          })
          const newFiles = { ...files, ...flattenArr(importFilesArr)}
          setFiles(newFiles)
          saveFilesToStore(newFiles)
          if(importFilesArr.length > 0) {
            remote.dialog.showMessageBox({
              type: 'info',
              title: `成功导入了${importFilesArr.length}个文件`,
              message: `成功导入了${importFilesArr.length}个文件`
            })
          }
        }
      }
    }).catch(err => {
      console.log(err)
    })
  }
  const fileListArr = (searchedFiles.length > 0) ? searchedFiles : filesArr
  const activeFile = files[activedFileId]
  const opendFiles = openedFileIDs.map(openID => {
    return files[openID]
  })
  const activeFileUploaded = () => {
    const { id } = activeFile
    const modifiedFile = {...files[id], isSynced: true, updatedAt: new Date().getTime()}
    const newFiles = {...files, [id]: modifiedFile}
    setFiles(newFiles)
    saveFilesToStore(newFiles)
  }
  const activeFileDownloaded = (event, message) => {
    if(!message.id) return
    const currentFile = files[message.id]
    const { id, path } = currentFile
    fileHelper.readFile(path).then(value => {
      let newFile
      if(message.status === 'download-success') {
        newFile = { ...files[id], body: value, isLoaded: true, isSynced: true, updatedAt: new Date().getTime()}
      } else{
        newFile = { ...files[id], body: value, isLoaded: true }
      }
      const newFiles = { ...files, [id]: newFile}
      setFiles(newFiles)
      saveFilesToStore(newFiles)
    })
  }
  const fileUploaded = () => {
    const newFiles = objToArr(files).reduce((result, file) => {
      const currentTime = new Date().getTime()
      result[file.id] = {
        ...files[file.id],
        isSynced: true,
        updatedAt: currentTime
      }
      return result
    }, {})
    setFiles(newFiles)
    saveFilesToStore(newFiles)
  }
  useIpcRenderer({
    'create-new-file': createNewFile,
    'import-file': importFiles,
    'save-edit-file': saveFile,
    'active-file-uploaded': activeFileUploaded,
    'file-downloaded': activeFileDownloaded,
    'files-uploaded': fileUploaded,
    'loading-status': (message, status) => { setLoading(status) }
  })
  return (
    <div className="App container-fluid px-0">
      { loading && <Loader></Loader> }
      <div className="row no-gutters">
        <div className="col-3 left-pannel d-flex flex-column">
          <FileSearch
            title="我的云文档"
            onFileSearch={ fileSearch }
          >            
          </FileSearch> 
          <FileList
            files={ fileListArr }
            onFileClick={ fileClick }
            onSaveEdit={ updateFileName }
            onFileDelete={ deleteFile }
          >            
          </FileList> 
          <div className="row no-gutters button-group">
            <div className="col">
              <ButtonBtn text="新建" colorClass="btn-primary" icon={faPlus} onBtnClick={ createNewFile }>            
              </ButtonBtn> 
            </div> 
            <div className="col">
              <ButtonBtn
                text="导入"
                colorClass="btn-success"
                icon={ faFileImport }
                onBtnClick={ importFiles }
              >          
              </ButtonBtn> 
            </div> 
          </div> 
        </div> 
        <div className="col-9 right-pannel d-flex flex-column">
          <TabList
            activedId={ activedFileId }
            files={ opendFiles }
            unsavedIds={ unsavedFilesIds }
            onCloseTab={ closeTab }
            onTabClick={ tabClick }
          >
          </TabList>
          {
            !activeFile && 
            <div className="start-page">
              选择或者创建新的文档
            </div>
          }
          {
            activeFile &&
            <>
              <Editor
                className="editor"
                init={{
                  height: 500,
                  language: "zh_CN",
                  statusbar: false,
                  plugins: [
                    "advlist autolink lists link image charmap print preview anchor",
                    "searchreplace visualblocks code fullscreen",
                    "insertdatetime media table paste code help wordcount",
                  ],
                  toolbar:
                    "undo redo | formatselect |fontselect fontsizeselect | bold italic backcolor forecolor |alignleft aligncenter alignright alignjustify | bullist numlist outdent indent | removeformat | help",
                }}
                value={ activeFile.body }
                onEditorChange={ (value) => { handleEditorChange(activedFileId, value) } }
              />
              { activeFile.isSynced && <div className="synced-box">已同步</div> }
               <ButtonBtn text="保存" colorClass="btn-primary" icon={faSave} onBtnClick={ saveFile }>            
              </ButtonBtn> 
            </>
          }
        </div>
      </div>
    </div>
  );
}

export default App;